/*
装饰器，
> 需要设置 tsconfig 中的 experimentalDecorators 为 true 来消除警告,
> 装饰器的本质是一个函数, 被修饰的那个目标可以是以下几种，装饰谁就写在谁的上一行，修饰方法的参数时写在参数前面；可以扩展类的属性和方法
> 修饰方法或属性时，需要使用 Object.defineProperty 来为装饰目标增加属性，装饰器函数的第三个参数就是属性描述器;
> 多个装饰器，先装饰属性。最后装饰类
1. 可以装饰类, 此时 target 是类本身, 
2. 修饰类的静态属性或静态方法，此时 target 是类本身,  
3. 装饰类的实例属性和实例方法，此时 target 是类的原型, target === 类.prototype

4. 装饰类的方法的参数；装饰器写在参数前面, 此时 target 是类的原型, 此时装饰器的参数是 targe t， key， index(第几个参数)
 */

// 装饰类


function addSay(target: any) {
    target.prototype.say = () => {
        console.log('哈哈---');
    }
}

// 需要设置 tsconfig 中的 experimentalDecorators 为 true 来消除警告
@addSay
class Person {
    private name!: string
    private readonly age!: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    say!: Function // 非空断言
    static getName() {
        console.log('全人类');
    }
    eat() {
        console.log('吃饭');
    }
}

let p = new Person('张三', 23)